package library.frame;

import library.logic.ManagementSystem;
import library.logic.Book;
import library.logic.Tema;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
import java.util.*;
import java.util.List;

/**
 * User: RockCrazy
 * Date: 03.01.12
 * Time: 1:37
 */
public class WinBook extends JDialog implements ActionListener
{
	// Владелец нашего окна - вводим для вызова нужного нам метода
	private MainFrame owner;

	// Результат нажатия кнопок
	private boolean result = false;

	// Параметры книги
	private int bookId = 0;
	private JTextField bookName = new JTextField();
	private JTextField author = new JTextField();
	private JTextField izdatel = new JTextField();
	private JTextField numIzdan = new JTextField();
	private JTextField yearIzdan = new JTextField();
	private JTextField kolvoStr = new JTextField();
	private JTextField price = new JTextField();
	private JComboBox temaList;
	private JCheckBox exist;
	private JSpinner datePrihod = new JSpinner(new SpinnerDateModel(new Date(), null, null, Calendar.DAY_OF_MONTH));
	private JTextField letterCode = new JTextField();
	private JTextField polka = new JTextField();
	private JTextArea prim = new JTextArea();
	private JTextArea oglav = new JTextArea();
	private JTextArea tag = new JTextArea();

	// Параметры окна
	private static final int D_HEIGHT = 550;    // высота окна
	private final static int D_WIDTH = 800;     // ширина окна
	private final static int L_X = 10;          // левая граница метки для поля
	private final static int L_W = 100;         // ширина метки для поля
	private final static int C_W = 150;         // ширина поля
	private ManagementSystem ms;
	private JTable booksTab;


	/**
	 * @param newBook знак добавления книг или исправление
	 * @param owner родительская форма
	 */
	public WinBook(List<Tema> temas, boolean newBook,  MainFrame owner)
	{
		// После вставки книг без закрытия окна нам потребуется перегрузка списка
		// А для этого нам надо иметь доступ к этому методу в главной форме
		this.owner = owner;
		try
		{
			ms = new ManagementSystem();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		// Установить заголовок
		setTitle("Информация о книгах");
		// Не будем использовать layout совсем
		getContentPane().setLayout(null);

		temaList = new JComboBox(new Vector<Tema>(temas));
		// Разместим компоненты по абсолютным координатам

		// Наименование
		JLabel lName = new JLabel("Название:", JLabel.RIGHT);
		lName.setBounds(L_X, 10, L_W, 20);      // X и Y координаты самой левой верхней точки компонента, ширина и высота.
		getContentPane().add(lName);
		bookName.setBounds(L_X + L_W + 10, 10, C_W, 20);
		getContentPane().add(bookName);

		// Автор
		JLabel lAuthor = new JLabel("Автор:", JLabel.RIGHT);
		lAuthor.setBounds(L_X, 35, L_W, 20);
		getContentPane().add(lAuthor);
		author.setBounds(L_X + L_W + 10, 35, C_W, 20);
		getContentPane().add(author);

		// Издательство
		JLabel lIzdatel = new JLabel("Издательство:", JLabel.RIGHT);
		lIzdatel.setBounds(L_X, 60, L_W, 20);
		getContentPane().add(lIzdatel);
		izdatel.setBounds(L_X + L_W + 10, 60, C_W, 20);
		getContentPane().add(izdatel);

		// Номер издания
		JLabel lNumIzdan = new JLabel("Номер издания:", JLabel.RIGHT);
		lNumIzdan.setBounds(L_X, 85, L_W, 20);
		getContentPane().add(lNumIzdan);
		numIzdan.setBounds(L_X + L_W + 10, 85, C_W, 20);
		getContentPane().add(numIzdan);

		// Год издания
		JLabel lYearIzdan = new JLabel("Год издания:", JLabel.RIGHT);
		lYearIzdan.setBounds(L_X, 110, L_W, 20);
		getContentPane().add(lYearIzdan);
		yearIzdan.setBounds(L_X + L_W + 10, 110, C_W, 20);
		getContentPane().add(yearIzdan);

		// Колво страниц
		JLabel lKolvoStr = new JLabel("Кол-во страниц:", JLabel.RIGHT);
		lKolvoStr.setBounds(L_X, 135, L_W, 20);
		getContentPane().add(lKolvoStr);
		kolvoStr.setBounds(L_X + L_W + 10, 135, C_W, 20);
		getContentPane().add(kolvoStr);

		// Цена
		JLabel lPrice = new JLabel("Цена:", JLabel.RIGHT);
		lPrice.setBounds(L_X, 160, L_W, 20);
		getContentPane().add(lPrice);
		price.setBounds(L_X + L_W + 10, 160, C_W, 20);
		getContentPane().add(price);

		// ID темы
		JLabel lIdTema = new JLabel("Тема:", JLabel.LEFT);
		lIdTema.setBounds(L_X, 185, L_W, 20);
		temaList.setBounds(L_X + L_W + 10, 185, C_W, 20);
		getContentPane().add(lIdTema);
		getContentPane().add(temaList);


		// Наличие в библиотеке
		exist = new JCheckBox("В наличии");
		exist.setSelected(false);
		exist.setBounds(L_X + L_W + 10, 210, 100, 25);
		getContentPane().add(exist);

		// Дата поступления в библиотеку
		JLabel lDatePrih = new JLabel("Дата регистрации:", JLabel.RIGHT);
		lDatePrih.setBounds(L_X, 235, L_W, 20);
		getContentPane().add(lDatePrih);
		datePrihod.setBounds(L_X + L_W + 10, 235, C_W, 20);
		getContentPane().add(datePrihod);

		// Буквенный код
		JLabel lLetterCode = new JLabel("Буквенный код:", JLabel.RIGHT);
		lLetterCode.setBounds(L_X, 260, L_W, 20);
		getContentPane().add(lLetterCode);
		letterCode.setBounds(L_X + L_W + 10, 260, C_W, 20);
		getContentPane().add(letterCode);

		// Полка
		JLabel lPolka = new JLabel("Полка:", JLabel.RIGHT);
		lPolka.setBounds(L_X, 285, L_W, 20);
		getContentPane().add(lPolka);
		polka.setBounds(L_X + L_W + 10, 285, C_W, 20);
		getContentPane().add(polka);

		// Примечание
		JLabel lPrim = new JLabel("Примечание:", JLabel.RIGHT);
		lPrim.setBounds(L_X, 310, L_W, 20);
		prim.setBounds(L_X + L_W + 10, 310, C_W, 40);
		prim.setLineWrap(true);
		getContentPane().add(lPrim);
		getContentPane().add(prim);

		// Оглавление
		JLabel lOglav = new JLabel("Оглавление:", JLabel.RIGHT);
		lOglav.setBounds(L_X, 335 + 20, L_W, 20);
		oglav.setBounds(L_X + L_W + 10, 355, C_W, 40);
		oglav.setLineWrap(true);
		getContentPane().add(lOglav);
		getContentPane().add(oglav);

		// Краткое содержание
		JLabel lTag = new JLabel("Содержание:", JLabel.RIGHT);
		lTag.setBounds(L_X, 400, L_W, 20);
		tag.setBounds(L_X + L_W + 10, 400, C_W, 70);
		tag.setLineWrap(true);
		getContentPane().add(lTag);
		getContentPane().add(tag);

		// Создаем таблицу для вывода списка книг
		booksTab = new JTable(1, 5);
		booksTab.getSelectionModel().addListSelectionListener(new RowListener());
		reloadBooks();
		JScrollPane scrollPane = new JScrollPane(booksTab);
		scrollPane.setBounds(L_X + 270, 10, 495, 465);
		getContentPane().add(scrollPane);


		JButton btnCancel = new JButton("Выход");
		btnCancel.setName("Выход");
		btnCancel.addActionListener(this);
		btnCancel.setBounds(675 , 480, 100, 25);
		getContentPane().add(btnCancel);

		// если newBook = true
		if (newBook)
		{
			JButton btnOk = new JButton("OK");
			btnOk.setName("OK");
			btnOk.addActionListener(this);
			btnOk.setBounds(465, 480, 100, 25);
			getContentPane().add(btnOk);

			JButton btnNew = new JButton("Добавить");
			btnNew.setName("Добавить");
			btnNew.addActionListener(this);
			btnNew.setBounds(570, 480, 100, 25);
			getContentPane().add(btnNew);
		}
		// если newBook = false
		else
		{
			JOptionPane.showMessageDialog(this, "<html><font color=red>Внимание! Включен режим редактирования!");
			JButton btnDel = new JButton("<html><font color=red>Удалить");
			btnDel.setName("Удалить");
			btnDel.addActionListener(this);
			btnDel.setBounds(465, 480, 100, 25);
			getContentPane().add(btnDel);

			setTitle("Редактирование читателей");
			JButton btnSave = new JButton("Сохранить");
			btnSave.setName("Сохранить");
			btnSave.addActionListener(this);
			btnSave.setBounds(570, 480, 100, 25);
			getContentPane().add(btnSave);
		}

		// Устанавливаем поведение формы при закрытии - не закрывать совсем.
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

		// Получаем размеры экрана
		Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
		// А теперь просто помещаем его по центру, вычисляя координаты на основе полученной информации
		setBounds(((int) d.getWidth() - WinBook.D_WIDTH) / 2, ((int) d.getHeight() - WinBook.D_HEIGHT) / 2, WinBook.D_WIDTH, WinBook.D_HEIGHT);

	}

	// Получить результат, true - кнопка ОК, false - кнопка Cancel
	public boolean getResult()
	{
		return result;
	}

	// Установить поля соответственно переданным данным о читателе
	public void setBook(Book book)
	{
		bookId = book.getBookId();
		bookName.setText(book.getBookName());
		author.setText(book.getAuthor());
		izdatel.setText(book.getIzdatel());
		numIzdan.setText(String.valueOf(book.getNumIzdan()));
		yearIzdan.setText(String.valueOf(book.getYearIzdan()));
		kolvoStr.setText(String.valueOf(book.getKolvoStr()));
		price.setText(String.valueOf(book.getPrice()));
		// TODO : Внести вместо temaId СomboBox
		for (int i = 0; i < temaList.getModel().getSize(); i++)
		{
			Tema tema = (Tema) temaList.getModel().getElementAt(i);
			if (tema.getTemaId() == book.getTemaId())
			{
				temaList.setSelectedIndex(i);
				break;
			}
		}
		exist.setSelected(book.isExist());
		datePrihod.getModel().setValue(book.getDatePrihod());
		letterCode.setText(book.getLetterCode());
		polka.setText(book.getPolka());
		prim.setText(book.getPrim());
		oglav.setText(book.getOglav());
		tag.setText(book.getTag());
	}

	// Вернуть данные в виде новой книги с соотвтествующими полями
	public Book getBook()
	{
		Book book = new Book();
		book.setBookId(bookId);
		book.setBookName(bookName.getText());
		book.setAuthor(author.getText());
		book.setIzdatel(izdatel.getText());
		book.setNumIzdan(Integer.parseInt(numIzdan.getText()));
		book.setYearIzdan(Integer.parseInt(yearIzdan.getText()));
		book.setKolvoStr(Integer.parseInt(kolvoStr.getText()));
		book.setPrice(new Double(price.getText()));
		// TODO : Внести вместо temaId СomboBox
		book.setTemaId(((Tema) temaList.getSelectedItem()).getTemaId());
		//book.setTemaId(Integer.parseInt(temaId.getText()));
		book.setExist(exist.isSelected());
		Date datePrih = ((SpinnerDateModel) datePrihod.getModel()).getDate();
		book.setDatePrihod(datePrih);
		book.setLetterCode(letterCode.getText());
		book.setPolka(polka.getText());
		book.setPrim(prim.getText());
		book.setOglav(oglav.getText());
		book.setTag(tag.getText());
		return book;
	}

	public void actionPerformed(ActionEvent aE)
	{
		JButton src = (JButton) aE.getSource();
		// Добавляем книгу, но не закрываем окно
		// Здесь мы не будем вызывать в отдельном потоке сохранение.
		// Оно не занимает много времени и лишние действия здесь не оправданы
		if (src.getName().equals("Добавить"))
		{
			result = true;
			try
			{
				ManagementSystem.getInstance().insertBook(getBook());
				reloadBooks();
				bookName.setText("");
				author.setText("");
				izdatel.setText("");
				numIzdan.setText("");
				yearIzdan.setText("");
				kolvoStr.setText("");
				price.setText("");
				// TODO : Внести вместо temaId СomboBox
				//temaId.setText("");
				temaList.setSelectedIndex(-1);
				exist.setSelected(false);
				datePrihod = new JSpinner(new SpinnerDateModel(new Date(), null, null, Calendar.DAY_OF_MONTH));
				letterCode.setText("");
				polka.setText("");
				prim.setText("");
				oglav.setText("");
				tag.setText("");
			}
			catch (Exception sql_e)
			{
				JOptionPane.showMessageDialog(this, sql_e.getMessage());
			}
			return;
		}
		if (src.getName().equals("Сохранить"))
		{
			result = true;
			try
			{
				ManagementSystem.getInstance().updateBook(getBook());
				reloadBooks();
			}
			catch (Exception sql_e)
			{
				JOptionPane.showMessageDialog(this, sql_e.getMessage());
			}
			return;
		}
		if (src.getName().equals("Удалить"))
		{
			result = true;
			deleteBook();
			bookName.setText("");
			author.setText("");
			izdatel.setText("");
			numIzdan.setText("");
			yearIzdan.setText("");
			kolvoStr.setText("");
			price.setText("");
			// TODO : Внести вместо temaId СomboBox
			//temaId.setText("");
			temaList.setSelectedIndex(-1);
			exist.setSelected(false);
			datePrihod = new JSpinner(new SpinnerDateModel(new Date(), null, null, Calendar.DAY_OF_MONTH));
			letterCode.setText("");
			polka.setText("");
			prim.setText("");
			oglav.setText("");
			tag.setText("");
			return;

		}

		// Смена ФЛАГА
		if (src.getName().equals("OK"))
		{
			result = true;
		}
		if (src.getName().equals("Выход"))
		{
			result = false;
		}
		setVisible(false);
	}

	/**
	 * метод для удаления книги
 	 */
	private void deleteBook()
	{
		try
		{
			ms = new ManagementSystem();
			Thread t = new Thread()
			{
				public void run()
				{
					if (booksTab != null)
					{
						BookTableModel stm = (BookTableModel) booksTab.getModel();
						// Проверяем - выделена ли хоть какая-нибудь книга
						if (booksTab.getSelectedRow() >= 0)
						{
							if (JOptionPane.showConfirmDialog(WinBook.this,
									"Вы хотите удалить книгу?", "Удаление книги",
									JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)
							{
								Book book = stm.getBook(booksTab.getSelectedRow());
								try
								{
									ms.deleteBook(book);
									reloadBooks();
								}
								catch (SQLException e)
								{
									JOptionPane.showMessageDialog(WinBook.this, e.getMessage());
								}
							}
						} // Если книга не выделена - сообщаем пользователю, что это необходимо
						else
						{
							JOptionPane.showMessageDialog(WinBook.this, "Необходимо выделить книгу в списке");
						}
					}
				}
			};
			t.start();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * Метод для обеспечения интерфейса ListSelectionListener
 	 */
	public void valueChanged(ListSelectionEvent e)
	{
		if (!e.getValueIsAdjusting())
		{
			reloadBooks();
		}

	}

	/**
	 *  метод для обновления списка КНИГ
	 */
	public void reloadBooks()
	{
		temaList.setSelectedIndex(-1);
		// Создаем анонимный класс для потока
		Thread t = new Thread()
		{
			// Переопределяем в нем метод run
			public void run()
			{
				if (booksTab != null)
				{
					try
					{
						// Получаем список книг
						Collection<Book> lBook = ms.getBooks();
						// И устанавливаем модель для таблицы с новыми данными
						booksTab.setModel(new BookTableModel(new Vector<Book>(lBook)));
					}
					catch (SQLException e)
					{
						JOptionPane.showMessageDialog(WinBook.this, e.getMessage());
					}
				}
			}
		};
		// И теперь мы запускаем наш поток
		t.start();
	}

	/**
	 * Метод для обеспечения интерфейса ChangeListener
	 * @param e
	 */
	public void stateChanged(ChangeEvent e)
	{
		reloadBooks();
	}

	/**
	 * Метод слушателя строк`
	 */
	private class RowListener implements ListSelectionListener
	{

		public void valueChanged(ListSelectionEvent event)
		{
			BookTableModel ctm = (BookTableModel) booksTab.getModel();
			Book cl = ctm.getBook(booksTab.getSelectedRow());

			if (event.getValueIsAdjusting())
			{
				return;
			}
			try
			{
				setBook(cl);
			}
			catch (Exception sql_e)
			{
				JOptionPane.showMessageDialog(WinBook.this, "Данные успешно сохранены");
			}
		}
	}
}
